3. 다양한 저수준 런타임

4.4 다양한 저수준 런타임

저수준 런타임(Low-level Runtime)이란?

저수준 런타임은 OCI가 정의한 인터페이스를 통해 고수준 런타임에서 지시를 받아 호스트와 격리된 실행 환경을 작성하고 조작하는 수단을 제공함. 컨테이너는 애플리케이션을 호스트와 격리된 실행 환경으로 작동시키는 기술이지만, 이런 실행 환경 작성법은 다양해서 저수준 런타임에 따라 여러 갈래가 있음

용어 정리

  • 저수준 런타임(Low-level Runtime): OCI 런타임이라고도 함. 실제로 컨테이너를 생성하고 실행하는 소프트웨어. 호스트 OS의 격리 기능(네임스페이스, cgroup 등)을 직접 다룸
  • 고수준 런타임(High-level Runtime): CRI 런타임(containerd, CRI-O)이라고도 함. 이미지 관리, 네트워크 설정 등을 담당하고 저수준 런타임을 호출하여 컨테이너 생성
  • OCI (Open Container Initiative): 컨테이너 표준을 제정하는 단체. Linux Foundation 산하 프로젝트

런타임 계층 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[kubelet / Docker CLI]
        │
        │ CRI API / Docker API
        ↓
[고수준 런타임]
    containerd, CRI-O, Docker Engine
        │
        │ OCI Runtime Spec
        ↓
[저수준 런타임 (OCI 런타임)]
    runc, gVisor, Kata Containers
        │
        │ 시스템 콜
        ↓
[호스트 OS / 커널]
    네임스페이스, cgroup, seccomp 등

4.4.1 runc

runc란?

runc는 OCI가 만든 참조 구현(Reference Implementation) 컨테이너 런타임. 원래는 도커의 일부로 개발된 libcontainer 라이브러리였는데 OCI에 양도됨

runc 개요:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[runc]
    │
    ├─ 개발: OCI (원래 Docker/libcontainer)
    ├─ 언어: Go
    ├─ 특징: OCI Runtime Spec의 참조 구현
    │
    ├─ 사용처:
    │   ├─ containerd (기본 런타임)
    │   ├─ CRI-O
    │   └─ Docker Engine
    │
    └─ 격리 기술: 리눅스 커널 기능 사용
        ├─ 네임스페이스 (Namespace)
        ├─ cgroup (Control Groups)
        ├─ seccomp (Secure Computing Mode)
        └─ AppArmor / SELinux

runc가 사용하는 리눅스 커널 기능:

리눅스 격리 기술:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[네임스페이스 (Namespace)]
    프로세스가 보는 시스템 자원을 격리
    │
    ├─ pid  : 프로세스 ID 격리 (컨테이너 내부에서 PID 1)
    ├─ net  : 네트워크 스택 격리 (별도 IP, 포트)
    ├─ mnt  : 파일시스템 마운트 격리
    ├─ uts  : 호스트명, 도메인명 격리
    ├─ ipc  : IPC(프로세스 간 통신) 격리
    ├─ user : 사용자/그룹 ID 격리
    └─ cgroup : cgroup 계층 격리 (v2)

[cgroup (Control Groups)]
    프로세스 그룹의 자원 사용량 제한/모니터링
    │
    ├─ cpu     : CPU 사용량 제한
    ├─ memory  : 메모리 사용량 제한
    ├─ blkio   : 블록 I/O 제한
    ├─ pids    : 프로세스 수 제한
    └─ devices : 디바이스 접근 제어

[seccomp (Secure Computing Mode)]
    프로세스가 호출할 수 있는 시스템 콜 제한
    │
    └─ 허용된 시스템 콜만 실행 가능
       위험한 시스템 콜 차단 → 보안 강화

[AppArmor / SELinux]
    강제적 접근 제어 (MAC)
    │
    └─ 파일, 네트워크 등에 대한 세밀한 접근 제어

runc의 격리 특성:

runc 격리 수준:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[호스트]
┌─────────────────────────────────────────┐
│              Host Kernel                │
│  ┌───────────┐  ┌───────────┐          │
│  │Container A│  │Container B│  ← 커널 공유
│  │  (runc)   │  │  (runc)   │          │
│  └───────────┘  └───────────┘          │
└─────────────────────────────────────────┘

특징:
├─ 장점: 가볍고 빠름 (VM 대비)
├─ 장점: 리소스 오버헤드 최소
└─ 단점: 커널을 공유하므로 격리가 VM보다 약함
         (커널 취약점 공격 가능성)
용어 정리

  • runc: OCI Runtime Specification의 참조 구현체. Docker, containerd, CRI-O의 기본 저수준 런타임
  • libcontainer: runc의 전신. 원래 Docker의 일부로 개발되었다가 OCI에 양도됨
  • 네임스페이스(Namespace): 프로세스가 보는 시스템 자원을 격리하는 Linux 커널 기능. pid, net, mnt, uts, ipc, user 등
  • cgroups (Control Groups): 프로세스 그룹의 자원 사용량을 제한하고 모니터링하는 Linux 커널 기능
  • seccomp (Secure Computing Mode): 프로세스가 호출할 수 있는 시스템 콜을 제한하는 보안 기능
  • AppArmor/SELinux: 파일, 네트워크 등에 대한 세밀한 접근 제어를 제공하는 강제적 접근 제어(MAC) 시스템


4.4.2 gVisor

gVisor란?

gVisor는 구글이 개발한 컨테이너 런타임. 구글 클라우드의 GKE Sandbox, Cloud Run 서비스에서 사용됨. gVisor는 사용자 공간 커널(User-space Kernel) 기술을 사용해서 호스트와 강력하게 격리된 컨테이너 실행 환경을 제공하는 점이 특징임

용어 정리

  • 사용자 공간(User Space): 일반 애플리케이션이 실행되는 영역. 커널 기능에 직접 접근 불가하며 시스템 콜을 통해 커널 기능 요청
  • 커널 공간(Kernel Space): OS 커널이 실행되는 영역. 하드웨어에 직접 접근 가능하며 시스템 콜 처리 담당
  • 시스템 콜(System Call): 애플리케이션이 커널 기능을 요청하는 인터페이스. 예: open(), read(), write(), fork() 등

gVisor 아키텍처:

gVisor 동작 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[일반 컨테이너 (runc)]

    [Application]
         │
         │ 시스템 콜
         ↓
    [Host Kernel] ← 직접 접근 (위험)

vs

[gVisor 컨테이너]

    [Application]
         │
         │ 시스템 콜
         ↓
    [Sentry] ← 사용자 공간 커널 (가로챔)
         │
         │ 제한된 시스템 콜만
         ↓
    [Host Kernel] ← 직접 접근 차단

gVisor 주요 컴포넌트:

gVisor 컴포넌트:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Sentry]
    │
    ├─ 역할: 사용자 공간에서 동작하는 커널
    ├─ 기능: 애플리케이션의 시스템 콜을 가로채서 처리
    │
    ├─ 동작 방식:
    │   ├─ seccomp: 시스템 콜 필터링
    │   └─ ptrace: 시스템 콜 추적/가로채기
    │
    └─ 특징: 호스트 커널로 보내는 시스템 콜 최소화
             대부분의 시스템 콜을 직접 구현

[Gofer]
    │
    ├─ 역할: 파일시스템 접근 프록시
    ├─ 기능: Sentry와 호스트 파일시스템 사이 중계
    │
    └─ 보안: Sentry가 직접 파일에 접근 못하게 격리
             별도 프로세스로 파일 I/O 처리

[runsc]
    │
    ├─ 역할: gVisor의 OCI 런타임 CLI
    └─ 기능: runc 대신 사용 가능 (OCI 호환)
gVisor 격리 다이어그램:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

┌─────────────────────────────────────────┐
│                Container                │
│  ┌─────────────────────────────────┐   │
│  │         Application              │   │
│  └──────────────┬──────────────────┘   │
│                 │ syscall              │
│                 ↓                      │
│  ┌─────────────────────────────────┐   │
│  │     Sentry (User-space Kernel)  │   │
│  │  ┌─────────────────────────┐    │   │
│  │  │ 시스템 콜 구현 (200+개) │    │   │
│  │  └─────────────────────────┘    │   │
│  └──────────────┬──────────────────┘   │
│                 │                      │
│        ┌───────┴───────┐              │
│        ↓               ↓              │
│  ┌──────────┐   ┌──────────┐          │
│  │  Gofer   │   │ 제한된   │          │
│  │(파일I/O) │   │시스템콜  │          │
│  └────┬─────┘   └────┬─────┘          │
└───────┼──────────────┼────────────────┘
        ↓              ↓
┌─────────────────────────────────────────┐
│              Host Kernel                │
│   (직접 접근 차단, 최소한의 인터페이스)  │
└─────────────────────────────────────────┘

gVisor 특징:

gVisor 장단점:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[장점]
    │
    ├─ 강력한 격리
    │   └─ 호스트 커널과 직접 통신 차단
    │      커널 취약점 공격 방어
    │
    ├─ runc보다 높은 보안
    │   └─ 멀티테넌트 환경에 적합
    │      신뢰할 수 없는 코드 실행 시 유용
    │
    └─ OCI 호환
        └─ 기존 컨테이너 이미지 그대로 사용

[단점]
    │
    ├─ 성능 오버헤드
    │   └─ 시스템 콜 가로채기로 인한 지연
    │      I/O 집약적 워크로드에서 성능 저하
    │
    ├─ 호환성 문제
    │   └─ 일부 시스템 콜 미구현
    │      모든 애플리케이션이 동작하지 않을 수 있음
    │
    └─ 리눅스 전용
        └─ Windows, macOS 미지원

[사용처]
    ├─ GKE Sandbox (Google Kubernetes Engine)
    ├─ Cloud Run (Google Cloud)
    └─ 멀티테넌트 SaaS 환경
용어 정리

  • gVisor: Google이 개발한 보안 강화 OCI 런타임. 사용자 공간 커널로 호스트 커널과 강력하게 격리
  • 사용자 공간 커널(User-space Kernel): 커널 기능을 사용자 공간에서 구현하여 호스트 커널 접근을 최소화하는 기술
  • Sentry: gVisor의 핵심 컴포넌트. 애플리케이션의 시스템 콜을 가로채서 사용자 공간에서 처리
  • Gofer: gVisor의 파일시스템 접근 프록시. Sentry와 호스트 파일시스템 사이를 중계
  • runsc: gVisor의 OCI 호환 런타임 CLI. runc 대신 사용하여 gVisor 컨테이너 실행
  • ptrace: 프로세스를 추적하고 시스템 콜을 가로채는 Linux 기능. gVisor가 시스템 콜 인터셉트에 사용
  • GKE Sandbox: Google Kubernetes Engine에서 gVisor를 사용하는 보안 강화 기능


4.4.3 Kata Containers

Kata Containers란?

오픈스택 재단에서 개발 중인 컨테이너 런타임으로 AKS(Azure)에서 미리보기 기능으로 채용했고 바이두(Baidu)가 제공하는 클라우드 서비스에서 도입한 사례가 있음. Kata Containers도 호스트와 강력하게 격리된 컨테이너 실행 환경을 제공하는 런타임인데 사용하는 기술이 gVisor와 다름

Kata Containers 개요:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Kata Containers]
    │
    ├─ 개발: OpenStack Foundation (현 Open Infrastructure)
    ├─ 기반: Intel Clear Containers + Hyper runV 통합
    │
    ├─ 핵심 기술:
    │   └─ 경량 가상머신 (Lightweight VM)
    │      각 파드/컨테이너를 별도 VM에서 실행
    │
    └─ OCI 호환: 기존 컨테이너 이미지 사용 가능

Kata Containers vs gVisor:

격리 방식 비교:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[gVisor]
    격리 방식: 사용자 공간 커널
    │
    └─ Sentry가 시스템 콜을 가로채서 처리
       호스트 커널 공유 (접근만 제한)

vs

[Kata Containers]
    격리 방식: 경량 가상머신 (VM)
    │
    └─ 각 컨테이너/파드마다 별도 VM 생성
       완전히 독립된 커널 사용 (커널 분리)

Kata Containers 아키텍처:

Kata Containers 동작 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[일반 컨테이너 (runc)]

┌─────────────────────────────────────────┐
│              Host Kernel                │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │Container│  │Container│  │Container│ │
│  │    A    │  │    B    │  │    C    │ │
│  └─────────┘  └─────────┘  └─────────┘ │
│         ↑ 커널 공유 (격리 약함)         │
└─────────────────────────────────────────┘

vs

[Kata Containers]

┌─────────────────────────────────────────┐
│              Host Kernel                │
│  ┌─────────────┐  ┌─────────────┐      │
│  │  VM (Pod A) │  │  VM (Pod B) │      │
│  │ ┌─────────┐ │  │ ┌─────────┐ │      │
│  │ │Guest    │ │  │ │Guest    │ │      │
│  │ │Kernel   │ │  │ │Kernel   │ │      │
│  │ ├─────────┤ │  │ ├─────────┤ │      │
│  │ │Container│ │  │ │Container│ │      │
│  │ └─────────┘ │  │ └─────────┘ │      │
│  └─────────────┘  └─────────────┘      │
│    ↑ 커널 분리 (VM 수준 격리)           │
└─────────────────────────────────────────┘

Kata Containers 컴포넌트:

Kata Containers 구성요소:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[kata-runtime]
    │
    ├─ 역할: OCI 호환 런타임 CLI
    └─ 기능: containerd/CRI-O와 연동

[kata-agent]
    │
    ├─ 역할: VM 내부에서 실행되는 에이전트
    ├─ 기능:
    │   ├─ 컨테이너 생성/관리
    │   ├─ 이미지 마운트
    │   └─ 네트워크 설정
    └─ 통신: vsock을 통해 호스트와 통신

[하이퍼바이저/VMM]
    │
    ├─ QEMU (기본)
    ├─ Firecracker (AWS)
    ├─ Cloud Hypervisor
    └─ ACRN (Intel)
하이퍼바이저/VMM 용어:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[하이퍼바이저 (Hypervisor)]
    │
    └─ 가상머신을 생성하고 관리하는 소프트웨어
       Type 1: 베어메탈 (ESXi, Xen)
       Type 2: 호스트 OS 위 (VirtualBox, VMware Workstation)

[VMM (Virtual Machine Monitor)]
    │
    └─ 가상머신을 실행하는 프로세스
       예: QEMU, Firecracker, Cloud Hypervisor

[Firecracker]
    │
    ├─ 개발: AWS
    ├─ 특징: 초경량 VMM (마이크로VM)
    ├─ 부팅 시간: ~125ms
    ├─ 메모리: ~5MB 오버헤드
    └─ 사용처: AWS Lambda, AWS Fargate

Kata Containers 특징:

Kata Containers 장단점:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[장점]
    │
    ├─ VM 수준 격리
    │   └─ 완전히 독립된 커널
    │      가장 강력한 격리
    │
    ├─ 호환성
    │   └─ 대부분의 리눅스 애플리케이션 동작
    │      gVisor보다 호환성 높음
    │
    └─ OCI 호환
        └─ 기존 컨테이너 이미지/워크플로우 사용

[단점]
    │
    ├─ 리소스 오버헤드
    │   └─ VM당 메모리/CPU 필요
    │      runc보다 무거움
    │
    ├─ 시작 시간
    │   └─ VM 부팅 필요 (Firecracker로 개선)
    │
    └─ 하드웨어 요구
        └─ 가상화 지원 필요 (Intel VT-x, AMD-V)

[사용처]
    ├─ AKS (Azure) - 미리보기
    ├─ Baidu Cloud
    └─ 높은 보안이 필요한 멀티테넌트 환경
용어 정리

  • Kata Containers: OpenStack Foundation에서 개발한 VM 기반 OCI 런타임. 각 파드/컨테이너를 별도 경량 VM에서 실행
  • 경량 가상머신(Lightweight VM): 최소한의 리소스로 빠르게 부팅되는 가상머신. 마이크로VM이라고도 함
  • kata-runtime: Kata Containers의 OCI 호환 런타임 CLI
  • kata-agent: VM 내부에서 실행되어 컨테이너를 관리하는 에이전트
  • 하이퍼바이저(Hypervisor): 가상머신을 생성하고 관리하는 소프트웨어. QEMU, Firecracker 등
  • Firecracker: AWS가 개발한 초경량 VMM. ~125ms 부팅, ~5MB 메모리 오버헤드. Lambda, Fargate에서 사용
  • vsock: VM과 호스트 간 통신을 위한 소켓. kata-agent가 호스트와 통신할 때 사용
  • Intel VT-x / AMD-V: 하드웨어 가상화 지원 기능. Kata Containers 실행에 필요


저수준 런타임 비교:

저수준 런타임 비교표:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

              runc         gVisor       Kata
─────────────────────────────────────────────
격리 방식    네임스페이스   사용자공간    VM
             cgroup       커널

격리 수준    중간          높음         매우 높음

성능         가장 빠름     중간         약간 느림
                         (I/O 느림)

호환성       매우 높음     제한적       높음
                         (syscall)

시작 시간    빠름          빠름         느림
                                      (VM 부팅)

메모리       최소          중간         높음
오버헤드

사용처       일반 워크로드  멀티테넌트   높은 보안
             대부분의 경우  SaaS        금융/의료
런타임 선택 가이드:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[일반적인 경우]
    └─ runc (기본)
       대부분의 워크로드에 적합

[멀티테넌트/신뢰할 수 없는 코드]
    └─ gVisor
       호환성 확인 필요

[최고 수준 보안 요구]
    └─ Kata Containers
       금융, 의료, 규제 환경

[클라우드 환경 권장]
    ├─ GKE: gVisor (GKE Sandbox)
    ├─ AKS: Kata Containers
    └─ AWS: Firecracker (Lambda, Fargate 내부)

4.5 OCI 표준 규격

도커와 쿠버네티스는 모두 동일한 이미지와 레지스트리를 다룰 수 있음. 따라서 docker build로 빌드한 이미지를 레지스트리를 통해 서로 공유할 수 있음. 런타임은 서로 호환성을 유지하면서 개발됨. 도커에서 사용하는 런타임을 runc에서 gVisor로 바꿔서 컨테이너를 실행할 수 있음

OCI 표준 규격 개요:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[OCI (Open Container Initiative)]
    │
    └─ 컨테이너 표준 제정 단체
       Docker, Google, CoreOS 등이 설립 (2015)
       Linux Foundation 산하

[OCI 표준 3가지]
    │
    ├─ OCI Runtime Specification
    │   └─ 저수준 런타임(runc 등)이 따르는 규격
    │
    ├─ OCI Image Specification
    │   └─ 컨테이너 이미지 형식 규격
    │
    └─ OCI Distribution Specification
        └─ 레지스트리 API 규격
OCI 표준이 보장하는 상호 운용성:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[이미지 빌드]
    Docker, Buildah, kaniko
         │
         │ OCI Image Spec
         ↓
[레지스트리]
    Docker Hub, GCR, ECR, Harbor
         │
         │ OCI Distribution Spec
         ↓
[고수준 런타임]
    containerd, CRI-O, Docker
         │
         │ OCI Runtime Spec
         ↓
[저수준 런타임]
    runc, gVisor, Kata

→ 모든 조합이 호환됨!
용어 정리

  • OCI (Open Container Initiative): 컨테이너 표준을 제정하는 단체. Docker, Google, CoreOS 등이 2015년 설립
  • 상호 운용성(Interoperability): 서로 다른 도구/플랫폼이 호환되어 함께 작동할 수 있는 특성. OCI 표준이 이를 보장


4.5.1 OCI Runtime Specification

OCI Runtime Specification이란?

OCI Runtime Specification은 OCI가 제정한 저수준 런타임 규격. 따라서 저수준 런타임은 종종 OCI 런타임이라고 부름. 저수준 런타임은 다양한 구현이 있지만 모두 런타임 규격을 따라서 개발되므로 고수준 런타임 같은 상위 컴포넌트에서 모두 동일한 방식으로 사용할 수 있음

OCI Runtime Spec 구성:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[OCI Runtime Specification]
    │
    ├─ Filesystem Bundle 규격
    │   └─ 컨테이너 생성에 필요한 파일 구조
    │
    ├─ Runtime Lifecycle
    │   └─ 컨테이너 생명주기 정의
    │
    └─ Runtime Operations
        └─ 컨테이너 조작 명령어 정의

파일시스템 번들 (Filesystem Bundle):

컨테이너를 작성하려면 먼저 기반이 필요함. 컨테이너 기반은 파일시스템 번들이라고 부름. 파일시스템 번들은 containerd를 비롯한 고수준 런타임이 이미지를 가져온 후에 이미지를 구성하는 파일들을 runc 등의 저수준 런타임에 넘길 때, 그 저장 방법을 정한 규격

파일시스템 번들 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Filesystem Bundle 디렉터리]
    │
    ├─ config.json          ← 실행 환경 설정 파일
    │   │
    │   ├─ ociVersion       : OCI 버전
    │   ├─ process          : 실행할 프로세스 정보
    │   │   ├─ args         : 실행 명령어 (엔트리포인트)
    │   │   ├─ env          : 환경 변수
    │   │   ├─ cwd          : 작업 디렉터리
    │   │   └─ user         : 실행 사용자
    │   │
    │   ├─ root             : 루트 파일시스템 경로
    │   ├─ hostname         : 호스트명
    │   │
    │   ├─ linux            : 리눅스 전용 설정
    │   │   ├─ namespaces   : 네임스페이스 설정
    │   │   ├─ resources    : cgroup 자원 제한
    │   │   └─ seccomp      : 시스템 콜 필터
    │   │
    │   └─ hooks            : 라이프사이클 훅
    │
    └─ rootfs/              ← 컨테이너 루트 파일시스템
        ├─ bin/
        ├─ etc/
        ├─ lib/
        ├─ usr/
        └─ ...

config.json 예시:

{
    "ociVersion": "1.0.2",
    "process": {
        "terminal": true,
        "user": { "uid": 0, "gid": 0 },
        "args": ["sh"],
        "env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "TERM=xterm"
        ],
        "cwd": "/"
    },
    "root": {
        "path": "rootfs",
        "readonly": false
    },
    "hostname": "my-container",
    "linux": {
        "namespaces": [
            { "type": "pid" },
            { "type": "network" },
            { "type": "ipc" },
            { "type": "uts" },
            { "type": "mount" }
        ],
        "resources": {
            "memory": { "limit": 536870912 },
            "cpu": { "shares": 1024 }
        }
    }
}
파일시스템 번들 생성 과정:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[1] 고수준 런타임이 이미지 풀
    containerd pull nginx:latest
         │
         ↓
[2] 이미지 레이어 추출
    레이어들을 로컬에 저장
         │
         ↓
[3] 파일시스템 번들 생성
    ├─ rootfs/ 디렉터리에 레이어 병합
    └─ config.json 생성 (이미지 설정 + kubelet 설정)
         │
         ↓
[4] 저수준 런타임 호출
    runc create --bundle /path/to/bundle container-id

컨테이너 생명 주기:

런타임 규격은 작성한 컨테이너의 생명주기도 정의함. 규격에 따르면 각 단계 중간에 훅(Hook) 실행 등의 처리가 들어가기도 하지만, 보통 4단계를 거침

컨테이너 생명주기:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[상태 전이도]

    (없음)
       │
       │ create
       ↓
   ┌────────┐
   │creating│ → 컨테이너 환경 준비 중
   └───┬────┘
       │ (완료)
       ↓
   ┌────────┐
   │created │ → 컨테이너 생성됨 (아직 실행 안 됨)
   └───┬────┘
       │ start
       ↓
   ┌────────┐
   │running │ → 컨테이너 실행 중
   └───┬────┘
       │ (프로세스 종료 또는 kill)
       ↓
   ┌────────┐
   │stopped │ → 컨테이너 중지됨
   └───┬────┘
       │ delete
       ↓
    (삭제됨)
생명주기 단계별 설명:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[1단계: create]
    파일시스템 번들을 OCI 호환 런타임에 지정해서 컨테이너 작성
    │
    ├─ 네임스페이스 생성
    ├─ cgroup 설정
    ├─ rootfs 마운트
    └─ 컨테이너 환경 준비 (프로세스는 아직 시작 안 함)

[2단계: start]
    컨테이너 실행 시작
    │
    ├─ 컨테이너 내부에서 init 프로세스 실행
    └─ 애플리케이션 시작

[3단계: (종료)]
    컨테이너 내부의 애플리케이션 종료
    │
    ├─ 정상 종료: 프로세스가 스스로 종료
    └─ 강제 종료: kill 명령으로 시그널 전송

[4단계: delete]
    컨테이너 삭제
    │
    ├─ cgroup 정리
    ├─ 네임스페이스 해제
    └─ 리소스 반환
용어 정리

  • 파일시스템 번들(Filesystem Bundle): 컨테이너 생성에 필요한 파일 구조. config.json과 rootfs 디렉터리로 구성
  • config.json: 컨테이너 설정 파일. 실행 명령, 환경 변수, 네임스페이스, cgroups 등 정의
  • rootfs: 컨테이너의 루트 파일시스템. 이미지 레이어를 병합하여 생성
  • 컨테이너 생명주기: creating → created → running → stopped 상태 전이
  • 생명주기 훅(Lifecycle Hooks): 컨테이너 상태 전이 시 실행되는 사용자 정의 스크립트


컨테이너 조작 명령어:

OCI Runtime 명령어:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[필수 명령어]

create <container-id>
    │
    └─ 컨테이너 생성 (아직 실행하지 않음)
       runc create --bundle ./mybundle mycontainer

start <container-id>
    │
    └─ 생성된 컨테이너 실행
       runc start mycontainer

kill <container-id> [signal]
    │
    └─ 컨테이너에 시그널 전송 (기본: SIGTERM)
       runc kill mycontainer SIGKILL

delete <container-id>
    │
    └─ 중지된 컨테이너 삭제
       runc delete mycontainer

state <container-id>
    │
    └─ 컨테이너 상태 확인 (JSON 출력)
       runc state mycontainer
runc state 출력 예시:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

$ runc state mycontainer

{
    "ociVersion": "1.0.2",
    "id": "mycontainer",
    "pid": 12345,
    "status": "running",
    "bundle": "/var/run/containers/mycontainer",
    "rootfs": "/var/run/containers/mycontainer/rootfs",
    "created": "2024-01-15T10:30:00.123456789Z"
}

규격에는 구현 방법에 별다른 제한은 없지만, 이런 조작은 저수준 런타임 실행 바이너리의 서브 명령어로 구현하는 경우가 많음


4.5.2 OCI Image Specification

OCI Image Specification이란?

OCI Image Specification은 OCI가 제정한 컨테이너 이미지 표준 규격. 컨테이너 이미지를 구성하는 컴포넌트와 디스크에서의 배치 방법, 각 컴포넌트 미디어 종류 등을 정의함

OCI Image Spec 구성요소:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[OCI Image]
    │
    ├─ 인덱스 (Index) - 선택사항
    │   └─ 멀티 아키텍처 지원
    │
    ├─ 매니페스트 (Manifest)
    │   └─ 이미지 설계도
    │
    ├─ 구성 파일 (Configuration)
    │   └─ 실행 설정 정보
    │
    └─ 레이어 (Layers)
        └─ 파일시스템 데이터

매니페스트 (Manifest):

이미지를 구성하는 핵심이 매니페스트 JSON 파일. 매니페스트는 컨테이너 이미지의 설계도 역할을 하고 이미지를 구성하는 다른 컴포넌트(레이어, 구성 파일 등)를 가리키는 디스크립터(Descriptor) 정보를 저장함

매니페스트 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Manifest]
    │
    ├─ schemaVersion: 2
    ├─ mediaType: "application/vnd.oci.image.manifest.v1+json"
    │
    ├─ config (디스크립터)
    │   └─ 구성 파일을 가리킴
    │
    └─ layers[] (디스크립터 배열)
        └─ 레이어들을 순서대로 가리킴
디스크립터 (Descriptor) 란?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Descriptor]
    다른 컴포넌트를 참조하는 메타데이터
    │
    ├─ mediaType : 컴포넌트 종류
    │   예: "application/vnd.oci.image.layer.v1.tar+gzip"
    │
    ├─ digest    : 컴포넌트의 해시값 (SHA256)
    │   예: "sha256:a3ed95caeb02..."
    │   용도: 무결성 검증, 고유 식별자
    │
    └─ size      : 컴포넌트 크기 (바이트)
        예: 1048576

매니페스트 예시:

{
    "schemaVersion": 2,
    "mediaType": "application/vnd.oci.image.manifest.v1+json",
    "config": {
        "mediaType": "application/vnd.oci.image.config.v1+json",
        "digest": "sha256:b5b2b2c507a0...",
        "size": 7023
    },
    "layers": [
        {
            "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
            "digest": "sha256:a3ed95caeb02...",
            "size": 32654
        },
        {
            "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
            "digest": "sha256:9f3eda2cfeca...",
            "size": 16724
        }
    ]
}

레이어 (Layer):

컨테이너 루트 파일시스템의 데이터는 레이어 구조. 레이어 데이터 형식에는 몇 가지 규격이 존재함

레이어 형식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[레이어 압축 형식]
    │
    ├─ tar+gzip (가장 일반적)
    │   mediaType: application/vnd.oci.image.layer.v1.tar+gzip
    │
    ├─ tar (비압축)
    │   mediaType: application/vnd.oci.image.layer.v1.tar
    │
    └─ tar+zstd (고성능 압축)
        mediaType: application/vnd.oci.image.layer.v1.tar+zstd
레이어 구조 예시:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Base Layer (ubuntu:22.04)]
    /bin, /lib, /usr, /etc...
         │
         │ (오버레이)
         ↓
[Layer 2 (apt install nginx)]
    /usr/sbin/nginx
    /etc/nginx/...
         │
         │ (오버레이)
         ↓
[Layer 3 (COPY app files)]
    /var/www/html/index.html

→ 최종 rootfs: 모든 레이어 병합

구성 파일 (Configuration):

구성 파일(Configuration)은 이미지를 컨테이너로 실행할 때 필요한 정보가 기록된 JSON 파일. 구성 파일에는 컨테이너에서 실행할 명령어(엔트리포인트), 사용자, 환경 변수, 루트 파일시스템을 구성하는 레이어 목록 등이 들어감. 고수준 런타임이 파일시스템 번들을 작성할 때 사용함

구성 파일 주요 내용:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Configuration]
    │
    ├─ architecture: "amd64"
    ├─ os: "linux"
    │
    ├─ config
    │   ├─ User        : 실행 사용자
    │   ├─ Env[]       : 환경 변수
    │   ├─ Entrypoint[]: 엔트리포인트
    │   ├─ Cmd[]       : 기본 명령어
    │   ├─ WorkingDir  : 작업 디렉터리
    │   └─ ExposedPorts: 노출 포트
    │
    ├─ rootfs
    │   ├─ type: "layers"
    │   └─ diff_ids[]: 레이어 다이제스트 목록
    │
    └─ history[]: 빌드 히스토리

구성 파일 예시:

{
    "architecture": "amd64",
    "os": "linux",
    "config": {
        "User": "nginx",
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "NGINX_VERSION=1.28.0"
        ],
        "Entrypoint": ["/docker-entrypoint.sh"],
        "Cmd": ["nginx", "-g", "daemon off;"],
        "WorkingDir": "/",
        "ExposedPorts": {
            "80/tcp": {}
        }
    },
    "rootfs": {
        "type": "layers",
        "diff_ids": [
            "sha256:a3ed95caeb02...",
            "sha256:9f3eda2cfeca..."
        ]
    }
}

인덱스 (Index):

인덱스는 선택사항 파일이지만 멀티 아키텍처에 대응하는 이미지를 만들 때 유용한 JSON 파일. 인덱스에는 매니페스트 참조 정보가 저장됨

인덱스 (멀티 아키텍처 지원):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Image Index]
    │
    └─ manifests[] (매니페스트 목록)
        │
        ├─ Manifest (linux/amd64)
        │   └─ digest: "sha256:abc123..."
        │      platform: { os: "linux", architecture: "amd64" }
        │
        ├─ Manifest (linux/arm64)
        │   └─ digest: "sha256:def456..."
        │      platform: { os: "linux", architecture: "arm64" }
        │
        └─ Manifest (windows/amd64)
            └─ digest: "sha256:ghi789..."
               platform: { os: "windows", architecture: "amd64" }
멀티 아키텍처 이미지 사용:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

$ docker pull nginx:latest

[런타임]
    │
    ├─ 인덱스 다운로드
    ├─ 현재 플랫폼 확인 (linux/amd64)
    ├─ 해당 플랫폼의 매니페스트 선택
    └─ 해당 이미지 레이어 다운로드

→ 사용자는 동일한 이미지 이름 사용
  런타임이 자동으로 적절한 아키텍처 선택

런타임은 이런 인덱스를 참조해서 자신이 실행된 노드 플랫폼에 맞는 매니페스트를 선택하고 가져올 수 있음

용어 정리

  • OCI Image Specification: 컨테이너 이미지 포맷 표준. 매니페스트, 레이어, 구성 파일의 구조 정의
  • 매니페스트(Manifest): 이미지의 설계도. 레이어와 구성 파일을 가리키는 디스크립터 정보 포함
  • 디스크립터(Descriptor): 다른 컴포넌트를 참조하는 메타데이터. mediaType, digest, size 포함
  • 다이제스트(Digest): 컴포넌트의 SHA256 해시값. 무결성 검증과 고유 식별에 사용
  • 레이어(Layer): 파일시스템 변경 사항을 담은 tar 아카이브. 보통 gzip으로 압축
  • 구성 파일(Configuration): 이미지 실행 설정 정보. Entrypoint, Cmd, Env 등 포함
  • 인덱스(Index): 멀티 아키텍처 지원을 위한 매니페스트 목록. linux/amd64, linux/arm64 등 플랫폼별 매니페스트 참조


4.5.3 OCI Distribution Specification

OCI Distribution Specification이란?

컨테이너 레지스트리 API를 정의하는 규격. 도커 레지스트리 HTTP API를 기반으로 규격이 만들어졌고 공통된 부분이 많음

OCI Distribution Spec 개요:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[OCI Distribution Specification]
    │
    └─ 컨테이너 레지스트리가 제공해야 하는 HTTP API 정의
       │
       ├─ 이미지 Pull API
       ├─ 이미지 Push API
       ├─ 태그 목록 조회 API
       └─ 카탈로그 API

주요 API 엔드포인트:

레지스트리 API:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Pull (이미지 다운로드)]

매니페스트 Pull
    GET /v2/<name>/manifests/<reference>
    │
    ├─ <name>: 이미지 이름 (예: library/nginx)
    └─ <reference>: 태그 또는 다이제스트
       예: latest, v1.28, sha256:abc123...

레이어/Blob Pull
    GET /v2/<name>/blobs/<digest>
    │
    └─ <digest>: 레이어의 SHA256 해시
       예: sha256:a3ed95caeb02...

[Push (이미지 업로드)]

매니페스트 Push
    PUT /v2/<name>/manifests/<reference>

레이어/Blob Push (2단계)
    1. POST /v2/<name>/blobs/uploads/
       → 업로드 세션 시작, Location 헤더 반환

    2. PUT /v2/<name>/blobs/uploads/<uuid>?digest=<digest>
       → 실제 데이터 업로드

[조회]

태그 목록
    GET /v2/<name>/tags/list

카탈로그 (리포지토리 목록)
    GET /v2/_catalog

이미지 Pull 흐름:

이미지 Pull 과정:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Runtime]                          [Registry]
    │                                  │
    │ GET /v2/library/nginx/manifests/latest
    │─────────────────────────────────→│
    │                                  │
    │←─────────────────────────────────│
    │ 200 OK + Manifest JSON           │
    │                                  │
    │ (매니페스트에서 레이어 다이제스트 추출)
    │                                  │
    │ GET /v2/library/nginx/blobs/sha256:abc...
    │─────────────────────────────────→│
    │                                  │
    │←─────────────────────────────────│
    │ 200 OK + Layer 1 (tar.gz)        │
    │                                  │
    │ GET /v2/library/nginx/blobs/sha256:def...
    │─────────────────────────────────→│
    │                                  │
    │←─────────────────────────────────│
    │ 200 OK + Layer 2 (tar.gz)        │
    │                                  │
    │ (모든 레이어 다운로드 완료)
    │                                  │
    ↓
[레이어 압축 해제 및 병합]
    │
    ↓
[컨테이너 rootfs 준비 완료]
용어 정리

  • OCI Distribution Specification: 컨테이너 레지스트리 API 표준. Docker Registry HTTP API를 기반으로 제정
  • 컨테이너 레지스트리: 컨테이너 이미지를 저장하고 배포하는 서버. Docker Hub, GCR, ECR, Harbor 등
  • Blob: 레지스트리에 저장된 바이너리 데이터. 레이어나 구성 파일이 blob으로 저장됨
  • 태그(Tag): 이미지 버전을 식별하는 이름. latest, v1.0, stable 등
  • 카탈로그(Catalog): 레지스트리에 저장된 모든 리포지토리(이미지) 목록

Pull 과정 상세:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[1] 매니페스트 다운로드
    │
    └─ 이미지 태그명으로 매니페스트 요청
       GET /v2/nginx/manifests/latest
       │
       └─ 응답: 매니페스트 JSON
          (레이어 목록, 구성 파일 참조 포함)

[2] 레이어 다운로드
    │
    └─ 매니페스트의 레이어 다이제스트로 각 레이어 요청
       GET /v2/nginx/blobs/sha256:a3ed95caeb02...
       │
       └─ 응답: tar.gz 압축 파일

[3] 레이어 압축 해제 및 병합
    │
    └─ 다운로드한 레이어들을 디스크에 압축 해제
       오버레이 파일시스템 등으로 중첩하여
       컨테이너의 rootfs로 사용

OCI 표준 핵심 정리:

OCI 표준 요약:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[OCI Runtime Specification]
    │
    ├─ 대상: 저수준 런타임 (runc, gVisor, Kata)
    ├─ 내용:
    │   ├─ Filesystem Bundle 구조
    │   ├─ 컨테이너 생명주기 (create, start, kill, delete)
    │   └─ config.json 형식
    └─ 효과: 런타임 교체 가능 (runc ↔ gVisor)

[OCI Image Specification]
    │
    ├─ 대상: 이미지 빌더, 런타임
    ├─ 내용:
    │   ├─ 매니페스트 (이미지 설계도)
    │   ├─ 레이어 (파일시스템 데이터)
    │   ├─ 구성 파일 (실행 설정)
    │   └─ 인덱스 (멀티 아키텍처)
    └─ 효과: 빌드 도구 교체 가능 (docker ↔ buildah)

[OCI Distribution Specification]
    │
    ├─ 대상: 컨테이너 레지스트리
    ├─ 내용:
    │   ├─ Pull API (매니페스트, 레이어)
    │   ├─ Push API
    │   └─ 태그/카탈로그 API
    └─ 효과: 레지스트리 교체 가능 (Docker Hub ↔ Harbor)
상호 운용성 다이어그램:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[빌드]                [저장]              [실행]
 │                      │                   │
 ├─ docker build        ├─ Docker Hub       ├─ runc
 ├─ buildah             ├─ Harbor           ├─ gVisor
 ├─ kaniko              ├─ GCR              ├─ Kata
 └─ Podman              └─ ECR              └─ ...
       │                      │                   │
       └──────────────────────┴───────────────────┘
                         │
                    OCI Standards
                         │
                 모든 조합이 호환됨!

참고 자료

공식 문서:

심화 자료: